<template>
  <div class="chat-container">
    <!--用户信息修改-->
    <modify-user-info v-model:is-open="modifyUserInfoIsOpen" />
    <!--表情弹窗-->
    <popup v-model:visible="isEmojiVisible" :position="emojiPosition">
      <emoji-box @on-emoji="handlerOnEmoji" />
    </popup>
    <div class="chat-bg">
      <div class="chat-box">
        <!-- 左侧菜单 -->
        <div class="box-left" :class="{ 'show-left': showLeft }">
          <div class="chat-list-title">
            <div class="relative flex">
              消息列表
            </div>
            <div class="close-btn" @click="showLeft = false">×</div>
          </div>
          <div class="chat-list-title-section">
            群聊
            <span v-if="totalGroupUnreadCount > 0" class="unread-count">{{ totalGroupUnreadCount }}</span>
          </div>
          <div class="chat-list-scroll-container">
          <div v-for="group in groupChatList" :key="group.id">
            <div
              class="chat-list-item"
              :class="{ selected: targetId === group.id }"
            @click="
            () => {
            targetId = group.id
            closeMask()
            }
            "
            >
              <avatar
                :info="{ name: group.name, avatar: group.avatar }"
                size="40px"
                :color="2"
                class="mr-[10px]"
              />
              <div class="chat-item-content">
                <div class="flex items-center mb-[5px]">
                  <div class="chat-content-name">{{ group.name }}</div>
                  <dot-hint
                    v-if="group.unreadCount > 0 && targetId !== group.id"
                    :text="group.unreadCount"
                  />
                </div>
                <div class="chat-content-msg">
                  <chat-list-content :msg="group.lastMessage || { content: '', type: 'text' }" />
                </div>
              </div>
            </div>
          </div>
          </div>
          <div
            v-if="privateChatList?.length > 0 && groupChatList.length === 0"
            class="chat-list-title-section">
            私聊
          </div>
          <div class="chat-list-title-section">
            私聊
            <span v-if="totalPrivateUnreadCount > 0" class="unread-count">{{ totalPrivateUnreadCount }}</span>
          </div>
          <div class="chat-list-content">
            <div
              v-for="item in privateChatList"
              :key="item.id"
              :class="['chat-list-item', targetId === item.targetId ? 'blue' : 'white']"
              @click="
                () => {
                  targetId = item.targetId
                  currentSelectTarget = item
                  closeMask()
                }
              "
            >
              <avatar :info="item.targetInfo" size="40px" class="mr-[10px]" />
              <div class="chat-item-content">
                <div class="flex items-center mb-[5px]">
                  <div class="chat-content-name">{{ item.targetInfo.name }}</div>
                  <dot-hint
                    v-if="item?.unreadCount > 0 && targetId !== item.targetId"
                    :text="item.unreadCount"
                  />
                </div>
                <div class="chat-content-msg">
                  <chat-list-content :is-group="false" :msg="item?.lastMessage" />
                </div>
              </div>
              <text-button
                v-if="targetId === item.targetId"
                text="移除"
                class="ml-[10px]"
                @click="() => onDeleteChatList(item.id)"
              />
            </div>
          </div>


        </div>
        <!-- 遮罩层 -->
        <div class="mask" v-if="showLeft || showRight" @click="closeMask"></div>
        <!-- 中间部分 -->
        <div class="box-middle">
          <div class="middle-top">
            <div class="menu-btn" @click="showLeft = true">
              <i class="iconfont icon-liebiao text-[24px]" />
            </div>
            <template v-if="isGroupChat(targetId)">
              <div class="group-info">
                <div class="group-name">
                  {{ currentGroup?.name }}（{{ currentGroupTotalMemberCount }}）
                </div>
              </div>
            </template>
            <template v-else>
              {{ currentSelectTarget?.targetInfo?.name }}
            </template>
            <div class="menu-btn" @click="showRight = true">
              <i class="iconfont icon-shezhi text-[24px]" />
            </div>
          </div>

          <div class="middle-content">
            <div class="chat-show-area" ref="chatShowAreaRef">
              <div v-if="isGroupChat(targetId)">
                <div
                  v-for="item in groupMsgRecords.get(targetId)"
                  :key="item.id"
                  :class="{ right: item.fromId === userInfoStore.userId }"
                >
                  <msg :msg="item" :user="msgStore.userListMap.get(item.fromId)" />
                </div>
              </div>
              <div v-else>
                <div
                  v-for="item in msgRecord"
                  :key="item.id"
                  :class="{ right: item.fromId === userInfoStore.userId }"
                >
                  <msg :msg="item" :user="msgStore.userListMap.get(item.fromId)" />
                </div>
              </div>
            </div>
            <div class="chat-input-area">
              <div class="chat-input">
                <div v-if="msgStore.referenceMsg" class="reference-msg">
                  <div
                    class="reference-msg-content"
                    v-if="msgStore.referenceMsg.type === MessageType.Text"
                  >
                    {{ msgStore.referenceMsg.fromInfo.name }} :
                    <text-msg :msg="msgStore.referenceMsg" />
                  </div>
                  <div
                    v-if="msgStore.referenceMsg.type === MessageType.Emoji"
                    class="flex items-center"
                  >
                    <div>{{ msgStore.referenceMsg.fromInfo.name }} :</div>
                    <emoji-msg height="40px" width="40px" :src="msgStore.referenceMsg.message" />
                  </div>
                  <div class="ml-[10px]">
                    <icon-button
                      @click="msgStore.referenceMsg = null"
                      size="20px"
                      font-size="12px"
                      icon="icon-shanchu"
                    />
                  </div>
                </div>
                <div class="flex items-center">
                  <div class="emoji-button mr-[10px]" @click="handlerSetEmojiBoxPosition">
                    <div class="iconfont icon-biaoqing text-[28px]" />
                  </div>
                  <div class="chat-msg-input">
                    <msg-input
                      v-model="msgContent"
                      ref="msgInputRef"
                      @send="handlerSubmitMsg"
                      :user="userListAll"
                      :is-at-popup="targetId === '1'"
                    />
                  </div>
                </div>
              </div>
              <div class="publish-button" @click="handlerSubmitMsg">
                <i class="iconfont icon-fasong2 text-[28px]" />
              </div>
            </div>
          </div>
        </div>

        <!-- 右侧菜单 -->
        <!-- 右侧菜单 -->
        <div class="box-right" :class="{ 'show-right': showRight }">
          <div class="right-top">
            <div class="flex items-center">
              <avatar
                :info="{ name: userInfoStore.userName, avatar: userInfoStore.avatar }"
                size="40px"
                class="mr-[5px] cursor-pointer"
                @click="modifyUserInfoIsOpen = true"
              />
              <div class="user-name">{{ userInfoStore.userName }}</div>
            </div>
            <div class="flex">
              <icon-button @click="handlerLogout" icon="icon-tuichu" />
            </div>
          </div>
          <div class="right-content">
            <!-- 群组聊天时只显示当前群成员 -->
            <div v-if="isGroupChat(targetId)" class="online-list">
              <div class="flex justify-between items-center mb-[10px]">
                <div class="text-[rgb(var(--text-color))] text-[14px] font-[600]">
                  群成员（{{ currentGroupOnlineCount }}）
                </div>
                <input
                  placeholder="搜索用户"
                  height="30px"
                  width="140px"
                  radius="5px"
                  font-size="14px"
                  v-model="userSearchValue"
                />
              </div>
              <div class="flex-1 overflow-y-auto pr-2" style="max-height: calc(100% - 120px);">
                <div class="online-list">
                <!-- 当前群成员列表 -->
              <div
                v-for="(item, index) in filteredGroupUserList"
                :key="item.userId"
                class="online-list-item"
                :class="{ odd: index % 2 === 0 }"
              >
                <div class="online-item-content">
                  <div class="w-[40px] h-[40px] relative">
                    <avatar :info="{ name: item.name, avatar: item.avatar }" size="40px" />
                    <div v-if="item.status?.includes('web')" class="absolute bottom-0 right-0 w-3 h-3 rounded-full bg-[rgb(var(--primary-color))] border border-white dark:border-gray-800"></div>
                  </div>
                  <div class="online-username">
                    {{ item.name }}
                    <span v-if="isGroupLeaderMap.get(item.userId)" class="group-leader-tag">群主</span>
                  </div>
                </div>

                <!-- 私聊按钮 -->
                <div class="online-item-operation ml-[20px]">
                  <text-button
                    v-if="item.userId !== userInfoStore.userId && item.type !== UserType.Bot"
                    text="私聊"
                    @click="
            () => {
              onCreatePrivateChat(item.userId)
              closeMask()
            }
          "
                  />
                  <text-button
                    v-if="isGroupLeaderMap.get(userInfoStore.userId) && item.userId !== userInfoStore.userId"
                    text="踢出"
                    @click="
      () => {
        showKickConfirmDialog = true
        selectedKickUserId = item.userId
      }
    "
                  />
                </div>
              </div>

                </div>
            </div>
              <!-- 退出按钮：sticky 定位 -->
              <div class="exit-button-sticky">
                <text-button
                  :text="isGroupLeader ? '解散群聊' : '退出群聊'"
                  @click="showExitGroupConfirm = true"
                />
              </div>
            </div>
            <!-- 私聊时显示用户列表和群聊列表 -->
            <template v-else>
              <!-- 群聊列表 -->
              <div class="flex justify-between items-center mb-[10px]">
                <div class="text-[rgb(var(--text-color))] text-[14px] font-[600]">
                  群列表（{{ allGroupList.length }}）
                </div>
                <input
                  placeholder="搜索群聊"
                  height="30px"
                  width="140px"
                  radius="5px"
                  font-size="14px"
                  v-model="groupSearchValue"
                />
              </div>
              <div class="flex-1 overflow-y-auto pr-2" style="max-height: calc(100% - 120px);">
                <div class="online-list">
                <div
                  v-for="(group, index) in filteredGroupList"
                  :key="group.id"
                  class="online-list-item"
                  :class="{ odd: index % 2 === 0 }"
                  >
                  <div class="online-item-content">
                    <div class="w-[40px] h-[40px] relative">
                      <avatar :info="{ name: group.name, avatar: group.avatar }" size="40px" />
                    </div>
                    <div class="online-username">{{ group.name }}</div>
                  </div>
                  <!-- 加入按钮：仅当用户未加入该群时显示 -->
                  <div v-if="!isUserInGroup(group.id)" class="online-item-operation ml-[20px]">
                    <text-button text="加入" @click="onJoinGroup(group.id)" />
                  </div>
                </div>
              </div>

              <!--创建群聊按钮-->
              <div class="create-group-button-sticky">
              <div
                class="flex items-center py-2 px-4 my-3 rounded-md cursor-pointer hover:bg-[rgba(var(--background-color),0.7)] transition-all duration-200"
                @click="showCreateGroupDialog = true"
              >
                <!-- 圆圈加号图标 -->
                <div class="w-6 h-6 rounded-full bg-[rgb(var(--primary-color))] flex justify-center items-center mr-2">
                  <svg class="w-4 h-4 text-white" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                    <line x1="12" y1="5" x2="12" y2="19"></line>
                    <line x1="5" y1="12" x2="19" y2="12"></line>
                  </svg>
                </div>
                <!-- 文字 -->
                <span class="text-[rgb(var(--text-color))] text-sm font-medium">创建群聊</span>
              </div>
              </div>
              </div>
            </template>
          </div>
        </div>
        <create-group-dialog
          v-model:visible="showCreateGroupDialog"
          :user-list="privateChatUserList"
          @submit="handleCreateGroup"
        />

      </div>
      <!-- 自定义退出群聊/解散群聊确认对话框 -->
      <confirm-dialog
        v-model:visible="showExitGroupConfirm"
        :title="isGroupLeader ? '确认解散群聊？' : '确认退出群聊？'"
        :content="isGroupLeader ? '您确定要解散该群聊吗？所有成员将被移除，此操作不可恢复。' : '您确定要退出当前群聊吗？此操作不可恢复。'"
        @confirm="isGroupLeader ? handleDisbandGroup() : handleExitGroup()"
        @cancel="() => (showExitGroupConfirm = false)"
      />
      <confirm-dialog
        v-model:visible="showKickConfirmDialog"
        title="确认踢出用户？"
        content="您确定要将该用户踢出群聊吗？此操作不可恢复。"
        @confirm="handleKickUser"
        @cancel="() => (showKickConfirmDialog = false)"
      />
    </div>
  </div>
</template>

<script setup>
import { computed, nextTick, onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import Input from '@/components/Input.vue'
import { useRouter } from 'vue-router'
import Avatar from '@/components/Avatar.vue'
import ChatListApi from '@/api/chatList.js'
import DotHint from '@/components/DotHint.vue'
import MessageApi from '@/api/message.js'
import EventBus from '@/utils/eventBus.js'
import UserApi from '@/api/user.js'
import Tooltip from '@/components/Tooltip.vue'
import ws from '@/utils/ws.js'
import { useToast } from '@/components/ToastProvider.vue'
import IconButton from '@/components/IconButton.vue'
import Msg from '@/components/Msg/Msg.vue'
import { useChatMsgStore } from '@/stores/useChatMsgStore.js'
import Popup from '@/components/Popup.vue'
import EmojiBox from '@/components/EmojiBox.vue'
import EmojiMsg from '@/components/Msg/MsgContent/EmojiMsg.vue'
import ChatListContent from '@/components/Msg/ChatListContent.vue'
import { MessageType } from '@/constant/messageType.js'
import { MessageSource } from '@/constant/messageSource.js'
import MsgInput from '@/components/MsgInput.vue'
import { UserType } from '@/constant/userType.js'
import TextMsg from '@/components/Msg/MsgContent/TextMsg.vue'
import Label from '@/components/Label.vue'
import ModifyUserInfo from '@/components/ModifyUserInfo.vue'
import { useUserInfoStore } from '@/stores/useUserInfoStore.js'
import Loading from '@/components/Loading.vue'
import ChatSkeleton from '@/components/ChatSkeleton.vue'
import UserlistApi from '@/api/userList'
import CreateGroupDialog from '@/components/CreateGroupDialog.vue'
import TextButton from '@/components/TextButton.vue'
import ConfirmDialog from '@/components/ConfirmDialog.vue'


const showExitGroupConfirm = ref(false)
const showCreateGroupDialog = ref(false)
let version = import.meta.env.VITE_CHAT_VERSION
const msgStore = useChatMsgStore()
const userInfoStore = useUserInfoStore()
const router = useRouter()
const showToast = useToast()
let recordIndex = 0
const showLeft = ref(false)
const showRight = ref(false)
const groupChatList = ref([])
const groupUserList = ref([])
// 私聊消息
const msgRecord = ref([])
//不同群组的消息
const groupMsgRecords = ref(new Map()) // key: groupId, value: message[]
const targetId = ref()
const currentSelectTarget = ref()
const msgContent = ref('')
const chatShowAreaRef = ref()
const isLoading = ref(false)
const isComplete = ref(false)
const onlineCount = ref(0)
const privateChatList = ref([])
const userSearchValue = ref('')
const currentNewMsgCount = ref(0)
const isEmojiVisible = ref(false)
const emojiPosition = ref()
const msgInputRef = ref()
const isGroupLeaderMap = ref(new Map())
const currentGroup = computed(() => {
  return groupChatList.value.find(g => g.id === targetId.value)
})
const isGroupLeader = computed(() => {
  return isGroupLeaderMap.value.get(userInfoStore.userId) === true
})

const modifyUserInfoIsOpen = ref(false)
const isSendLoading = ref(false)
let chatRecordLoadingTimer = null
const isChatRecordLoading = ref(false)
// 判断是否为群聊 ID
function isGroupChat(id) {
  return id?.startsWith('group_')
}
const currentGroupOnlineCount = computed(() => {
  if (!isGroupChat(targetId.value)) return 0
  return groupUserList.value.filter(user => user.status?.includes('web')).length
})
const currentGroupTotalMemberCount = computed(() => {
  if (!isGroupChat(targetId.value)) return 0
  return groupUserList.value.length
})
const filteredGroupUserList = computed(() => {
  // 如果没有输入内容，直接返回原始群成员列表
  if (!userSearchValue.value) return groupUserList.value;

  const keyword = userSearchValue.value.trim().toLowerCase();
  if (!keyword) return groupUserList.value;

  return groupUserList.value.filter(user =>
    user.name?.toLowerCase().includes(keyword)
  );
});
const groupSearchValue = ref('')


// 过滤群组
const filteredGroupList = computed(() => {
  if (!groupSearchValue.value) return allGroupList.value

  const keyword = groupSearchValue.value.trim().toLowerCase()
  return allGroupList.value.filter(group =>
    group.name?.toLowerCase().includes(keyword)
  )
})
// 获取私聊列表中的用户（即已经在私聊列表中存在的用户）
const privateChatUserList = computed(() => {
  const userIdsInPrivateChats = privateChatList.value.map(chat => chat.targetId);
  // 将 Map 转为数组
  const allUsers = Array.from(msgStore.userListMap.values());
  // 过滤出私聊用户
  return allUsers.filter(user => userIdsInPrivateChats.includes(user.id));
});
const showKickConfirmDialog = ref(false)
const selectedKickUserId = ref(null)

// 群主踢出成员
const handleKickUser = async () => {
  const userId = selectedKickUserId.value
  const groupId = targetId.value

  if (!userId || !groupId) {
    showToast('参数错误', true)
    return
  }

  try {
    const res = await UserlistApi.exit({
      userId,
      groupId
    })

    if (res.code === 0) {
      showToast('已成功踢出用户')
      onGetGroupUsers(groupId) // 刷新当前群成员列表
    } else {
      showToast(`踢出失败：${res.msg}`, true)
    }
  } catch (error) {
    console.error('踢出用户失败:', error)
    showToast('网络错误，请稍后再试', true)
  } finally {
    showKickConfirmDialog.value = false
    selectedKickUserId.value = null
  }
}
// 解散群聊
const handleDisbandGroup = async () => {
  const groupId = targetId.value

  if (!groupId) {
    showToast('群组信息异常', true)
    return
  }

  try {
    const res = await UserlistApi.disbandGroup({
      groupId,
      ownerId: userInfoStore.userId
    })

    if (res.code === 0) {
      showToast('群聊已成功解散')

      // 👇 清理本地状态
      groupChatList.value = groupChatList.value.filter(g => g.id !== groupId)
      groupUserList.value = []

      msgStore.referenceMsg = null
      clearUnreadCountInLocal(groupId)

      await onGetGroupChat()
      await onGetPrivateChatList()
      // 👇 手动刷新数据
      await onGetGroupChat()
      await onGetPrivateChatList()

      router.push({ path: '/', query: { t: Date.now() }})
    } else {
      showToast(res.msg || '解散群聊失败', true)
    }
  } catch (err) {
    console.error('解散群聊异常:', err)
    showToast('网络错误，请稍后再试', true)
  } finally {
    showExitGroupConfirm.value = false
  }
}


//退群
const handleExitGroup = async () => {
  const userId = userInfoStore.userId
  const groupId = targetId.value

  if (!userId || !groupId) {
    showToast('参数错误', true)
    return
  }

  try {
    const res = await UserlistApi.exit({ userId, groupId })

    if (res.code === 0) {
      showToast('已退出群聊')
      // 可选：切换到其他聊天或刷新页面
      targetId.value = '1' // 切换到默认会话
      onGetGroupChat() // 刷新左侧群聊列表
      groupUserList.value = [] // 清空当前群成员
    } else {
      showToast(`退出失败：${res.msg}`, true)
    }
  } catch (error) {
    console.error('退出群聊失败:', error)
    showToast('网络错误，请稍后再试', true)
  } finally {
    showExitGroupConfirm.value = false
  }
}

const onJoinGroup = (groupId) => {
  UserlistApi.join({ userId: userInfoStore.userId, groupId, role: 'user' }).then(res => {
    if (res.code === 0||res.data) {
      showToast('加入群聊成功')
      onGetGroupChat() // 刷新左侧群聊列表
      targetId.value = groupId // 自动切换到该群聊
    } else {
      showToast('加入失败：' + res.msg, true)
    }
  })
}
const handleCreateGroup = async (data) => {
  try {
    const res = await UserlistApi.create({
      ...data,
      userId: userInfoStore.userId,
      leader: userInfoStore.userName,
    })

    if (res.code === 0 && res.data?.groupId) {
      showToast('群聊创建成功')
      const groupId = res.data.groupId
      targetId.value = groupId

      // 批量加入成员
      if ((data.members || []).length > 0) {
        await Promise.all(
          data.members.map(async (userId) => {
            try {
              const joinRes = await UserlistApi.invite({
                targetUserId:userId,
                groupId,
                role: 'user' })
              if (joinRes.code !== 0) {
                console.warn(`添加用户 ${userId} 失败：`, joinRes.msg)
              }
            } catch (err) {
              console.error(`添加用户 ${userId} 出错：`, err)
            }
          })
        )
        onGetGroupUsers(groupId) // 刷新当前群成员列表
      }

      // 自动切换到新群聊并刷新左侧群聊列表
      onGetGroupChat()
    } else {
      showToast(`创建失败：${res.msg}`, true)
    }
  } catch (error) {
    console.error("创建群聊失败:", error)
    showToast("创建失败：" + error.message, true)
  }
}


const allGroupList = ref([]) // 所有群聊列表
const allGroupSearchValue = ref('') // 所有群聊搜索框内容

// 获取所有群聊
const onGetAllGroupList = () => {
  ChatListApi.groupall().then((res) => {
    if (res.code === 0) {
      allGroupList.value = res.data || []
    }
  })
}


// 判断当前用户是否是某个群组的成员
const isUserInGroup = (groupId) => {
  return groupChatList.value.some(group => group.id === groupId)
}



const checkIsGroupLeader = async (groupId, userId) => {
  if (!groupId || !userId) return false

  try {
    const response = await UserlistApi.getGroupOwnerId({ groupId })

    if (response.code === 0) {
      const leaderId = response.data
      const result = leaderId === userId
      isGroupLeaderMap.value.set(userId, result)
    } else {
      isGroupLeaderMap.value.set(userId, false)
    }
  } catch (error) {
    console.error('获取群主信息失败:', error)
    isGroupLeaderMap.value.set(userId, false)
  }
}

// 获取当前群聊消息记录
function getCurrentGroupMessages(groupId) {
  return groupMsgRecords.value.get(groupId) || []
}
// 保存未读数到 localStorage
function saveUnreadCountToLocal(groupId, count) {
  const unreadMap = JSON.parse(localStorage.getItem('groupUnreadCounts') || '{}')
  unreadMap[groupId] = count
  localStorage.setItem('groupUnreadCounts', JSON.stringify(unreadMap))
}
// 获取群组成员列表
const onGetGroupUsers = (groupId) => {
  UserlistApi.getGroupUsers({ groupId }).then((res) => {
    if (res.code === 0) {
      const usersWithStatus = res.data.map(user => {
        const globalUser = msgStore.userListMap.get(user.userId)
        return {
          ...user,
          status: globalUser?.status || []
        }
      })

      groupUserList.value = usersWithStatus

      // 批量检查每位成员是否为群主
      usersWithStatus.forEach(user => {
        checkIsGroupLeader(groupId, user.userId)
      })
    } else {
      groupUserList.value = []
    }
  })
}


// 从 localStorage 获取未读数
function getUnreadCountFromLocal(groupId) {
  const unreadMap = JSON.parse(localStorage.getItem('groupUnreadCounts') || '{}')
  return unreadMap[groupId] || 0
}

// 清除某个群聊的未读数
function clearUnreadCountInLocal(groupId) {
  const unreadMap = JSON.parse(localStorage.getItem('groupUnreadCounts') || '{}')
  delete unreadMap[groupId]
  localStorage.setItem('groupUnreadCounts', JSON.stringify(unreadMap))
}

msgStore.$subscribe(() => {
  const { scrollTop, clientHeight, scrollHeight } = chatShowAreaRef.value
  const isBottom = scrollTop + clientHeight >= scrollHeight - 1
  if (isBottom) {
    scrollToBottom()
  }
})



const handleScroll = () => {
  if (chatShowAreaRef.value) {
    //最底部更新currentNewMsgCount为0
    const { scrollTop, clientHeight, scrollHeight } = chatShowAreaRef.value
    const isBottom = scrollTop + clientHeight >= scrollHeight - 1
    if (isBottom) currentNewMsgCount.value = 0
    if (chatShowAreaRef.value.scrollTop === 0 && !isLoading.value) {
      onGetMsgRecord()
    }
  }
}



const userList = computed(() => {
  const values = Array.from(msgStore.userListMap.values())
  if (userSearchValue.value) {
    return values.filter((item) => item.name.includes(userSearchValue.value))
  } else {
    return values
  }
})

const userListAll = computed(() => {
  const values = []
  for (const [, value] of msgStore.userListMap) {
    values.push({ name: value.name, id: value.id, type: value.type })
  }
  return values
})
const totalGroupUnreadCount = computed(() => {
  return groupChatList.value.reduce((sum, group) => sum + (group.unreadCount || 0), 0)
})

const totalPrivateUnreadCount = computed(() => {
  return privateChatList.value.reduce((sum, chat) => sum + (chat.unreadCount || 0), 0)
})

const handlerSetEmojiBoxPosition = (e) => {
  const rect = e.target.getBoundingClientRect()
  emojiPosition.value = { top: rect.top, left: rect.left }
  isEmojiVisible.value = !isEmojiVisible.value
}

const handlerOnEmoji = (emoji, type) => {
  isEmojiVisible.value = false
  if (type === 'text') {
    nextTick(() => {
      msgInputRef.value.insertInputText(emoji)
    })
  } else {
    //图片链接
    let msg = {
      content: emoji,
      type: 'emoji',
    }
    onSendMsg(msg)
  }
}

//接收到消息
const handlerReceiveMsg = (data) => {
  // 如果是当前用户自己发送的消息，且已经本地插入过了，就不重复处理
  if (data.fromId === userInfoStore.userId) {
    return;
  }

  // 撤回消息特殊处理
  if (data.type === MessageType.Recall) {
    console.info('【撤回消息】开始处理:', data);
    handlerReceiveRecallMsg(data);
    return;
  }

  const isBottom = isAtBottom();
  const isGroup = isGroupChat(data.toId);

  // 统一处理消息更新
  if (isGroup) {
    const sender = msgStore.userListMap.get(data.fromId);
    const message = {
      ...data,
      fromInfo: {
        id: data.fromId,
        name: sender?.name || "未知用户",
        avatar: sender?.avatar || "",
      },
    };
    updateGroupChat(data.toId, message); // ✅ 统一处理群聊消息
  } else {
    updatePrivateChat(data); // ✅ 统一处理私聊消息
  }

  // 滚动处理
  if (!isBottom) {
    currentNewMsgCount.value++;
  } else {
    scrollToBottom();
  }
};

// 处理私聊消息更新
const updatePrivateChat = (message) => {
  let found = false;

  // 在私聊列表中查找对应的聊天
  for (let i = 0; i < privateChatList.value.length; i++) {
    const chat = privateChatList.value[i];
    if (message.fromId === chat.targetId || message.toId === chat.targetId) {
      found = true;

      // 更新最后一条消息
      chat.lastMessage = message;

      // 如果当前不在该私聊会话中，则增加未读计数
      if (targetId.value !== chat.targetId) {
        chat.unreadCount += 1;
      }
      break;
    }
  }

  // 如果没找到，可能是新的私聊，重新获取私聊列表
  if (!found) {
    onGetPrivateChatList();
  }

  // 如果当前会话正是该私聊，则将消息添加到消息记录中
  if (targetId.value === message.fromId || targetId.value === message.toId) {
    msgRecord.value.push(message);
  }
};

// 更新群聊未读数 & 最后一条消息
function updateGroupChat(groupId, message) {
  const group = groupChatList.value.find(g => g.id === groupId)
  if (!group) return

  // +++ 添加消息防重机制 +++
  const addMessageIfNotExists = (messages, newMsg) => {
    if (!messages.some(msg => msg.id === newMsg.id)) {
      messages.push(newMsg)
      return true
    }
    return false
  }

  // 更新群组消息记录
  if (isGroupChat(groupId)) {
    let messages = groupMsgRecords.value.get(groupId) || []
    if (message.type === MessageType.Recall) {
      console.info('【群聊撤回】处理撤回消息:', message);

      const index = messages.findIndex(m => m.id === message.id)
      if (index !== -1) {
        messages.splice(index, 1, {
          ...messages[index],
          type: message.type,
          message: message.message
        })

        groupMsgRecords.value.set(groupId, [...messages])
        console.info(`【群聊撤回】消息 ${message.id} 已更新`)
      } else {
        console.warn('【群聊撤回】未找到要撤回的消息:', message.id)
      }
    }else {
      if (addMessageIfNotExists(messages, message)) {
        groupMsgRecords.value.set(groupId, [...messages])
      }
    }
  }

  // 更新未读数
  if (targetId.value !== groupId) {
    group.unreadCount += 1;
    saveUnreadCountToLocal(groupId, group.unreadCount);
  }

  // 更新最后消息预览
  const groupIndex = groupChatList.value.findIndex(g => g.id === groupId)
  if (groupIndex !== -1) {
    groupChatList.value.splice(groupIndex, 1, {
      ...groupChatList.value[groupIndex],
      lastMessage: message
    })
  }
}
function updateGroupUserListStatus(userId, newStatus) {
  const index = groupUserList.value.findIndex(u => u.userId === userId)
  if (index !== -1) {
    groupUserList.value[index].status = newStatus
  }
}

//接收到通知
// 在 onMounted 内部或 script setup 其他位置找到 handlerReceiveNotify
const handlerReceiveNotify = (data) => {
  let user = msgStore.userListMap.get(data.content.id)
  if (!user) {
    user = data.content
    msgStore.userListMap.set(user.id, user)
  }

  switch (data.type) {
    case 'web-online':
      if (!user.status) {
        user.status = ['web']
      } else if (!user.status.includes('web')) {
        user.status.push('web')
      }
      handlerUserListSort()
      updateGroupUserListStatus(user.id, user.status)
      break
    case 'web-offline':
      if (user.status) {
        user.status = user.status.filter(s => s !== 'web')
        updateGroupUserListStatus(user.id, user.status)
      }
      break
  }
}




onMounted(async () => {
  EventBus.on('on-receive-msg', handlerReceiveMsg)
  if (chatShowAreaRef.value) {
    chatShowAreaRef.value.addEventListener('scroll', handleScroll)
  }
  onGetGroupChat()
  onGetPrivateChatList()
  await onGetGroupChat()
  await onGetPrivateChatList()
  await onGetUserListMap()
  await onGetOnlineWeb()
  // 获取所有群聊
  await onGetAllGroupList()
  targetId.value = '1'
  EventBus.on('on-receive-notify', handlerReceiveNotify)
  handlerUserListSort()


  // 获取所有群组的最新消息

  // 👇 新增：刷新后主动拉取所有群组未读数
  setTimeout(() => {
    groupChatList.value.forEach(group => {
      ChatListApi.readStatus({ targetId: group.id }).then(res => {
        if (res.code === 0 && res.data?.unreadCount > 0) {
          const count = res.data.unreadCount
          group.unreadCount = count
          saveUnreadCountToLocal(group.id, count)
        }
      })
    })
  }, 500)
})

onUnmounted(() => {
  //EventBus.off('on-receive-msg', handlerReceiveMsg)
  EventBus.off('on-receive-notify', handlerReceiveNotify)
})

const scrollToBottom = () => {
  if (chatShowAreaRef.value) {
    nextTick(() => (chatShowAreaRef.value.scrollTop = chatShowAreaRef.value.scrollHeight))
  }
}


//获取聊天记录
const onGetMsgRecord = () => {
  if (isLoading.value || isComplete.value || !targetId.value) return
  isLoading.value = true

  const container = chatShowAreaRef.value
  const scrollTopBeforeLoad = container?.scrollTop || 0
  const scrollHeightBeforeLoad = container?.scrollHeight || 0

  MessageApi.record({ targetId: targetId.value, index: recordIndex, num: 20 }).then((res) => {
    if (res.code === 0) {
      const newMessages = res.data.reverse()
      if (newMessages.length > 0) {
        if (isGroupChat(targetId.value)) {
          const existing = groupMsgRecords.value.get(targetId.value) || []
          groupMsgRecords.value.set(targetId.value, [...newMessages, ...existing])
        } else {
          msgRecord.value = [...newMessages, ...msgRecord.value]
        }
        recordIndex += newMessages.length
        restoreScrollPosition(scrollTopBeforeLoad, scrollHeightBeforeLoad)
      } else {
        isComplete.value = true
      }
    }
  }).finally(() => {
    isLoading.value = false
  })
}

const restoreScrollPosition = (prevScrollTop, prevScrollHeight) => {
  nextTick(() => {
    if (chatShowAreaRef.value) {
      const newScrollHeight = chatShowAreaRef.value.scrollHeight
      chatShowAreaRef.value.scrollTop = prevScrollTop + (newScrollHeight - prevScrollHeight)
    }
  })
}

const isAtBottom = () => {
  const { scrollTop, clientHeight, scrollHeight } = chatShowAreaRef.value
  return scrollTop + clientHeight >= scrollHeight - 1
}

//已读会话
const onReadChatList = (id) => {
  if (isGroupChat(id)) {
    const group = groupChatList.value.find(g => g.id === id)
    if (group) {
      group.unreadCount = 0
      clearUnreadCountInLocal(id) // 清除本地记录
    }
    return
  }

  for (let i = 0; i < privateChatList.value.length; i++) {
    let chat = privateChatList.value[i]
    if (id === chat.targetId) {
      chat.unreadCount = 0
      break
    }
  }
  ChatListApi.read({ targetId: id })
}


watch(
  targetId,
  (newValue, oldValue) => {
    msgContent.value = ''
    recordIndex = 0
    msgRecord.value = []
    isComplete.value = false
    isLoading.value = false
    isChatRecordLoading.value = false
    chatRecordLoadingTimer = setTimeout(() => {
      isChatRecordLoading.value = true
    }, 100)
    onGetMsgRecord()

    if (oldValue) {
      onReadChatList(oldValue)
      if (isGroupChat(oldValue)) {
        groupChatList.value = [...groupChatList.value]
      } else {
        privateChatList.value = [...privateChatList.value]
      }
    }

    if (isGroupChat(newValue)) {
      const group = groupChatList.value.find(g => g.id === newValue)
      if (group && group.lastMessage) {
        ChatListApi.read({ targetId: newValue }) // 👈 新增这行代码
      }
      onGetGroupUsers(newValue) // 获取当前群组用户列表
    } else {
      groupUserList.value = [] // 清空群组用户列表
    }
  },
  { immediate: true },
)


const closeMask = () => {
  showLeft.value = false
  showRight.value = false
}

//退出登录
const handlerLogout = () => {
  localStorage.removeItem('x-token')
  userInfoStore.clearUserInfo()
  ws.disConnect()
  router.push('/login')
}
function updateGroupLastMessage(groupId, message) {
  const index = groupChatList.value.findIndex(g => g.id === groupId)
  if (index !== -1) {
    groupChatList.value.splice(index, 1, {
      ...groupChatList.value[index],
      lastMessage: message
    })
  }
}

// 获取群聊
const onGetGroupChat = () => {
  ChatListApi.groupList().then((res) => {
    if (res.code === 0) {
      const groups = res.data || []

      groupChatList.value = res.data.map(group => {
        const unreadCountRef = ref(
          getUnreadCountFromLocal(group.id) !== 0
            ? getUnreadCountFromLocal(group.id)
            : (group.unreadCount || 0)
        )
        return reactive({
          ...group,
          lastMessage: null, // 初始化为 null
          get unreadCount() {
            return unreadCountRef.value
          },
          set unreadCount(val) {
            unreadCountRef.value = val
          }
        })
      })

      // 👇 新增：刷新后主动拉取所有群组的最新消息
      ChatListApi.latestmessage().then(res => {
        if (res.code === 0) {
          res.data.forEach(item => {
            // 手动补全 fromInfo.name
            const sender = msgStore.userListMap.get(item.latestMessage.fromId)
            const messageWithFromName = {
              ...item.latestMessage,
              fromInfo: {
                id: item.latestMessage.fromId,
                name: sender?.name || '未知用户',
                avatar: sender?.avatar || ''
              }
            }

            updateGroupLastMessage(item.groupId, messageWithFromName)
          })
        }
      })
    }
  })
}

const handlerSubmitMsg = () => {
  const nodeLists = msgInputRef.value?.getNodeList()
  console.log('nodeLists:', nodeLists) // 调试查看结构
  if (!nodeLists || !Array.isArray(nodeLists) || nodeLists.length === 0) {
    showToast('请输入内容', true)
    return
  }

  let msg = {
    content: JSON.stringify(nodeLists),
    type: MessageType.Text,
  }
  onSendMsg(msg)


}


//发送消息
const onSendMsg = (msg) => {
  const time = setTimeout(() => {
    isSendLoading.value = true
    scrollToBottom()
  }, 300)

  MessageApi.send({
    targetId: targetId.value,
    source: isGroupChat(targetId.value) ? MessageSource.Group : MessageSource.User,
    msgContent: msg.content,
    referenceMsgId: msgStore.referenceMsg?.id,
    type: msg.type,
  }).then((res) => {
    if (res.code === 0) {
      const message = res.data

      // 手动补充 fromInfo.name 字段
      message.fromInfo = {
        id: userInfoStore.userId,
        name: userInfoStore.userName,
        avatar: userInfoStore.avatar
      }

      if (isGroupChat(targetId.value)) {
        updateGroupChat(targetId.value, message)
      } else {
        msgRecord.value.push(message)
      }

      recordIndex++
      scrollToBottom()
    }
  }).finally(() => {
    isSendLoading.value = false
    clearTimeout(time)
    msgContent.value = ''
  })

  msgStore.referenceMsg = null
}


//删除私聊列表内容
const onDeleteChatList = (id) => {
  ChatListApi.delete({ chatListId: id }).then((res) => {
    if (res.code === 0) {
      onGetPrivateChatList()
    }
  })
}

//获取用户列表
const onGetUserListMap = async () => {
  await UserApi.listMap().then((res) => {
    if (res.code === 0) {
      msgStore.setUserListMap(new Map(Object.entries(res.data)))
    }
  })
}

//获取web在线人员
const onGetOnlineWeb = async () => {
  await UserApi.onlineWeb().then((res) => {
    if (res.code === 0) {
      const onlineWeb = res.data
      for (let i = 0; i < onlineWeb?.length; i++) {
        const user = msgStore.userListMap.get(onlineWeb[i])
        user.status = Array.isArray(user.status) ? [...user.status, 'web'] : ['web']
      }
    }
  })
}

//排序
const handlerUserListSort = () => {
  const sortedEntries = [...msgStore.userListMap.entries()].sort(([, a], [, b]) => {
    if (a?.type === UserType.Bot && b?.type !== UserType.Bot) return -1
    if (b?.type === UserType.Bot && a?.type !== UserType.Bot) return 1
    const aStatus = a?.status || []
    const bStatus = b?.status || []
    const aStatusEmpty = aStatus.length === 0
    const bStatusEmpty = bStatus.length === 0
    if (aStatusEmpty && !bStatusEmpty) return 1
    if (!aStatusEmpty && bStatusEmpty) return -1
    return 0
  })
  msgStore.userListMap = new Map(sortedEntries)
  let onlineNum = 0
  for (let [, value] of msgStore.userListMap) {
    if (value.type === UserType.Bot) {
      continue
    }
    if (value?.status?.length > 0) {
      onlineNum++
    } else {
      break
    }
  }
  onlineCount.value = onlineNum
}

//接受到已撤回的消息
const handlerReceiveRecallMsg = (msg) => {
  console.log('【执行撤回】原始消息:', msg);
  let found = false;
  for (let i = msgRecord.value.length - 1; i >= 0; i--) {
    console.log(`【对比 id】msg.id=${msg.id}, 当前 msgRecord[${i}].id=${msgRecord.value[i].id}`);
    if (msgRecord.value[i].id === msg.id) {
      console.info(`【匹配成功】正在替换第 ${i} 条消息`);
      // 使用 splice 触发响应式更新
      msgRecord.value.splice(i, 1, {
        ...msgRecord.value[i],
        type: msg.type,
        message: msg.message
      });
      break
      found = true;
    }
  }
  if (!found) {
    console.error('【未找到对应消息】无法撤回:', msg.id);
  } else {
    console.info('【撤回成功】消息已更新');
  }
}

// 获取私聊列表
const onGetPrivateChatList = async () => {
  await ChatListApi.privateList().then((res) => {
    if (res.code === 0) {
      privateChatList.value = res.data.map(chat => {
        const unreadCountRef = ref(chat.unreadCount || 0)
        return reactive({
          ...chat,
          get unreadCount() {
            return unreadCountRef.value
          },
          set unreadCount(val) {
            unreadCountRef.value = val
          }
        })
      })
    }
  })
}



//创建私聊
const onCreatePrivateChat = (id) => {
  ChatListApi.create({ targetId: id }).then(async (res) => {
    if (res.code === 0) {
      currentSelectTarget.value = res.data
      await onGetPrivateChatList()
      targetId.value = id
    }
  })
}
</script>

<style lang="less" scoped>
.chat-container {
  width: 100%;
  height: 100%;
  position: absolute;
  background: var(--screen-bg-color);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;

  .chat-bg {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    background-image:
      linear-gradient(225deg, #ffffff, #ff6ec7),
      linear-gradient(135deg, #ffffff, #007BFF);

    background-size: cover;
    background-blend-mode: soft-light;
  }

  .mask {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: rgba(0, 0, 0, 0.1);
    z-index: 10;
  }

  .chat-box {
    width: 80%;
    height: 90%;
    display: flex;
    position: relative;
    min-width: 0;

    @media screen and (max-width: 900px) {
      width: 95%;
      height: 95%;
    }

    .box-left {
      width: 280px;
      min-width: 280px;
      background-color: rgba(var(--background-color), 0.5);
      backdrop-filter: blur(8px);
      margin-right: 5px;
      border-radius: 5px;
      border: rgba(var(--background-color), 0.5) 3px solid;
      display: flex;
      flex-direction: column;
      padding: 0 10px;

      @media screen and (max-width: 900px) {
        position: fixed;
        left: -280px;
        top: 0;
        bottom: 0;
        margin: 0;
        z-index: 11;
        transition: all 0.3s;
        background-color: rgba(var(--background-color), 0.9);

        &.show-left {
          left: 0;
        }
      }

      .vcard {
        cursor: pointer;
        height: 60px;
        border-radius: 5px;
        background-size: cover;
        background-repeat: no-repeat;
        background-position: center;
      }

      .chat-list-title {
        color: rgb(var(--text-color));
        height: 60px;
        min-height: 60px;
        display: flex;
        align-items: center;
        justify-content: center;
        font-size: 18px;
        line-height: 18px;
        font-weight: 600;
        user-select: none;

        @media screen and (max-width: 900px) {
          justify-content: space-between;
        }
      }

      .chat-list-title-section {
        font-size: 14px;
        font-weight: bold;
        color: rgb(var(--text-color));
        padding: 5px 10px;
        margin: 10px 0 5px;
        background-color: rgba(var(--background-color), 0.3);
        border-radius: 5px;
        user-select: none;
      }

      .unread-count {
        margin-left: 8px;
        padding: 2px 6px;
        font-size: 12px;
        color: #fff;
        background-color: rgb(var(--primary-color));
        border-radius: 12px;
        vertical-align: middle;
      }

      .chat-list-item {
        height: 60px;
        margin-bottom: 6px;
        border-radius: 6px;
        display: flex;
        align-items: center;
        padding: 10px;
        cursor: pointer;
        user-select: none;
        transition: background-color 0.3s ease;

        &:hover {
          background-color: rgba(var(--background-color), 0.7);
        }

        .chat-item-content {
          display: flex;
          flex-direction: column;
          justify-content: space-between;
          flex: 1;
          overflow: hidden;

          .chat-content-name {
            font-size: 14px;
            color: rgb(var(--text-color));
          }

          .chat-content-msg {
            width: 100%;
            font-size: 12px;
            color: rgba(var(--text-color), 0.6);
            white-space: nowrap;
            overflow: hidden;
            text-overflow: ellipsis;
          }
        }

        // 群聊选中样式新增
        &.selected,
        &.blue {
          background-color: rgb(var(--primary-color));

          &:hover {
            background-color: rgba(var(--primary-color), 0.7);
          }

          .chat-item-content {
            .chat-content-name {
              color: #ffffff;
            }

            .chat-content-msg {
              color: rgba(255, 255, 255, 0.8);
            }
          }
        }

        &.white,
        &.black {
          background-color: rgba(var(--background-color), 0.5);

          .chat-item-content {
            .chat-content-name {
              color: rgb(var(--text-color));
            }

            .chat-content-msg {
              color: rgba(var(--text-color), 0.6);
            }
          }

          &:hover {
            background-color: rgba(var(--background-color), 0.7);
          }
        }
      }

      .chat-list-content {
        flex: 1;
        overflow-y: scroll;
        padding-right: 5px;
        margin-right: -10px;
        margin-bottom: 20px;
      }

      .chat-list-scroll-container {
        max-height: 250px;
        overflow-y: auto;
        padding-right: 5px;

        &::-webkit-scrollbar {
          width: 6px;
        }

        &::-webkit-scrollbar-thumb {
          background-color: rgba(var(--text-color), 0.3);
          border-radius: 3px;
        }
      }
    }

    .box-middle {
      min-width: 300px;
      flex: 1;
      margin-right: 5px;
      border-radius: 5px;
      display: flex;
      flex-direction: column;

      @media screen and (max-width: 900px) {
        margin: 0;
      }

      .middle-top {
        height: 60px;
        min-height: 60px;
        background-color: rgba(var(--background-color), 0.5);
        backdrop-filter: blur(8px);
        margin-bottom: 5px;
        border-radius: 5px;
        border: rgba(var(--background-color), 0.5) 3px solid;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 0 15px;
        font-size: 18px;
        font-weight: 600;
        user-select: none;
        color: rgb(var(--text-color));

        .menu-btn {
          cursor: pointer;
          font-size: 24px;
        }

        @media screen and (max-width: 900px) {
          justify-content: space-between;
        }

        @media screen and (min-width: 900px) {
          .menu-btn {
            display: none;
          }
        }
      }

      .middle-content {
        flex: 1;
        min-height: 300px;
        border-radius: 5px;
        background-image: linear-gradient(
          130deg,
          rgba(var(--background-color), 0.3),
          rgba(var(--background-color), 0.5)
        );
        backdrop-filter: blur(10px);
        border: rgba(var(--background-color), 0.5) 3px solid;
        display: flex;
        flex-direction: column;

        .chat-show-area {
          flex: 1;
          padding: 10px;
          display: flex;
          flex-direction: column;
          overflow-y: scroll;

          .msg-item {
            display: flex;
          }

          .new-msg-count {
            position: fixed;
            right: 15px;
            bottom: 80px;
            padding: 4px 15px;
            border-radius: 20px;
            background-color: rgba(var(--background-color), 0.8);
            backdrop-filter: blur(10px);
            color: rgba(var(--primary-color));
            font-size: 14px;
            user-select: none;
            border: rgba(var(--background-color)) 2px solid;
            font-weight: 600;
            display: flex;
            justify-content: center;
            align-items: center;
            cursor: pointer;
          }
        }

        .chat-input-area {
          display: flex;
          align-items: center;
          justify-content: center;
          padding: 0 10px;
          margin: 15px 0;

          .chat-input {
            width: 80%;
            background-color: rgba(var(--background-color), 0.5);
            border-radius: 10px;
            overflow: hidden;
            padding: 10px;
            display: flex;
            flex-direction: column;

            .chat-msg-input {
              flex: 1;
              width: 0;
            }

            .emoji-button {
              width: 28px;
              height: 28px;
              user-select: none;
              cursor: pointer;
              display: flex;
              justify-content: center;
              align-items: center;
              color: rgba(var(--text-color), 0.5);
              flex-shrink: 1;
            }

            .reference-msg {
              font-size: 14px;
              display: flex;
              align-items: center;
              justify-content: space-between;
              background-color: rgba(var(--text-color), 0.1);
              color: rgba(var(--text-color), 0.9);
              border-radius: 5px;
              padding: 5px 10px;
              margin-bottom: 5px;
              user-select: none;

              .reference-msg-content {
                overflow: hidden;
                white-space: nowrap;
                text-overflow: ellipsis;
                word-break: break-word;
              }
            }
          }

          .publish-button {
            height: 55px;
            width: 55px;
            border-radius: 50px;
            background-color: rgb(var(--primary-color));
            border: rgba(var(--background-color), 0.5) 3px solid;
            display: flex;
            justify-content: center;
            align-items: center;
            color: #ffffff;
            cursor: pointer;
            margin-left: 10px;
          }
        }
      }
    }

    .box-right {
      width: 280px;
      min-width: 280px;
      border-radius: 5px;
      display: flex;
      flex-direction: column;

      @media screen and (max-width: 900px) {
        position: fixed;
        right: -280px;
        top: 0;
        bottom: 0;
        margin: 0;
        z-index: 11;
        transition: all 0.3s;

        &.show-right {
          right: 0;
        }

        .right-top {
          background-color: rgba(var(--background-color), 0.9) !important;
        }

        .right-content {
          background-color: rgba(var(--background-color), 0.9) !important;
        }
      }

      .right-top {
        height: 60px;
        min-height: 60px;
        background-color: rgba(var(--background-color), 0.5);
        backdrop-filter: blur(8px);
        margin-bottom: 5px;
        border-radius: 5px;
        border: rgba(var(--background-color), 0.5) 3px solid;
        display: flex;
        align-items: center;
        padding: 5px;
        user-select: none;
        justify-content: space-between;

        .user-name {
          font-size: 16px;
          font-weight: 600;
          color: rgb(var(--text-color));
        }

        .user-operate {
          font-size: 14px;
          font-weight: 600;
          color: rgb(var(--primary-color));
          cursor: pointer;
        }
      }

      .right-content {
        flex: 1;
        min-height: 300px;
        background-color: rgba(var(--background-color), 0.5);
        backdrop-filter: blur(8px);
        border-radius: 5px;
        border: rgba(var(--background-color), 0.5) 3px solid;
        padding: 5px;
        display: flex;
        flex-direction: column;

        .online-list {
          max-height: 400px; // 控制最大高度，根据需要调整
          overflow-y: auto;
          overflow-x: hidden;
          padding-right: 8px;
          margin-right: -8px;
          flex: 1;

          &::-webkit-scrollbar {
            width: 6px;
          }

          &::-webkit-scrollbar-thumb {
            background-color: rgba(var(--text-color), 0.3);
            border-radius: 3px;
          }

          &::-webkit-scrollbar-track {
            background-color: transparent;
          }

          .online-list-item {
            display: flex;
            justify-content: space-between;
            align-items: center;
            height: 50px;
            padding: 0 12px;
            border-radius: 6px;
            background-image: linear-gradient(to right, rgba(var(--minor-color), 0.1), rgba(var(--minor-color), 0));
            margin-bottom: 6px;
            transition: background-color 0.3s ease;
            position: relative;

            &:hover {
              background-color: rgba(var(--background-color), 0.7);
            }

            .online-item-content {
              display: flex;
              align-items: center;
              gap: 10px;
              overflow: hidden;
              flex: 1;
            }

            .online-username {
              font-size: 14px;
              color: rgb(var(--text-color));
              white-space: nowrap;
              overflow: hidden;
              text-overflow: ellipsis;
              max-width: 120px;
            }

            .online-status {
              position: absolute;
              width: 12px;
              height: 12px;
              border-radius: 10px;
              right: 8px;
              bottom: 8px;
              background-color: rgb(var(--primary-color));
              border: #ffffff 2px solid;
            }

            .online-item-operation {
              opacity: 0;
              transition: opacity 0.3s ease;
              pointer-events: none;
            }

            &:hover .online-item-operation {
              opacity: 1;
              pointer-events: auto;
            }

            &.odd {
              background-image: linear-gradient(to left, rgba(var(--minor-color), 0.1), rgba(var(--minor-color), 0));
            }

            @media screen and (max-width: 900px) {
              .online-item-operation {
                opacity: 1;
                pointer-events: auto;
              }
            }
          }
        }
      }
    }
  }

  .close-btn {
    cursor: pointer;
    font-size: 24px;
    padding: 0 10px;

    @media screen and (min-width: 900px) {
      display: none;
    }
  }
}
.exit-button-sticky {
  position: sticky;
  bottom: 16px; /* 距离底部距离 */
  //background-color: rgba(var(--background-color), 0.5); // 可选：背景色避免穿透
  padding: 8px 0;
  z-index: 1;

  &:empty {
    display: none;
  }
}
.create-group-button-sticky {
  position: sticky;
  bottom: 16px; /* 距离底部距离 */
  //background-color: rgba(var(--background-color), 0.5); // 可选背景色
  padding: 8px 0;
  z-index: 1;

  &:empty {
    display: none;
  }
}


.group-leader-tag {
  margin-left: 5px;
  background-color: #ffd700;
  color: #333;
  font-size: 12px;
  padding: 2px 6px;
  border-radius: 4px;
}
</style>

